﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using System.IO.IsolatedStorage;
using Microsoft.Phone.Info;

using System.Security.Cryptography;
using System.Text;
using VodafoneLiveTile;

namespace H3GLiveTile
{

    public static class Storage
    {
        #region Account
        public static Account LoadAccount()
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (var streamFile = appStorage.OpenFile("account.xml", FileMode.OpenOrCreate))
                {
                    try
                    {
                        XmlSerializer serializer = new XmlSerializer(typeof(Account));
                        using (var reader = new StreamReader(streamFile))
                        {
                            //var a = serializer.Deserialize(reader) as List<Account>;
                            //for (int i = 0; i < a.Count; i++)
                            //    a[i].messaggingService = MessaggingServices.GetServices(a[i].serviceType);
                            return serializer.Deserialize(reader) as Account;
                        }
                    }
                    catch (Exception) { return new Account(); }
                }
            }
        }

        public static void DeleteAccount()
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                appStorage.DeleteFile("account.xml");
            }
        }

        public static void SaveAccount(Account account)
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                appStorage.DeleteFile("account.xml");
                using (var streamFile = appStorage.OpenFile("account.xml", FileMode.OpenOrCreate))
                using (var writer = new StreamWriter(streamFile))
                //write_options_state(writer, entry);
                {
                    XmlSerializer serializer = new XmlSerializer(typeof(Account));
                    serializer.Serialize(writer, account);
                }
            }
        }
        #endregion


        #region SavedOptions
        /*
        public static SavedOptions LoadSavedOptions()
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (var streamFile = appStorage.OpenFile("SavedOptions.xml", FileMode.OpenOrCreate))
                {
                    try
                    {
                        XmlSerializer serializer = new XmlSerializer(typeof(SavedOptions));
                        using (var reader = new StreamReader(streamFile))
                            return serializer.Deserialize(reader) as SavedOptions;
                    }
                    catch (Exception) { return new SavedOptions(); }
                }
            }
        }

        public static void DeleteSavedOptions()
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                appStorage.DeleteFile("SavedOptions.xml");
            }
        }

        public static void SaveSavedOptions(SavedOptions state)
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                appStorage.DeleteFile("SavedOptions.xml");
                using (var streamFile = appStorage.OpenFile("SavedOptions.xml", FileMode.OpenOrCreate))
                using (var writer = new StreamWriter(streamFile))
                //write_options_state(writer, entry);
                {
                    XmlSerializer serializer = new XmlSerializer(typeof(SavedOptions));
                    serializer.Serialize(writer, state);
                }
            }
        }
        */
        #endregion

        #region Counters

        public static List<Counter> LoadCounters()
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (var streamFile = appStorage.OpenFile("contracts.xml", FileMode.OpenOrCreate))
                {
                    try
                    {
                        XmlSerializer serializer = new XmlSerializer(typeof(List<Counter>));
                        using (var reader = new StreamReader(streamFile))
                            return serializer.Deserialize(reader) as List<Counter>;
                    }
                    catch (Exception) { return new List<Counter>(); }
                }
            }
        }

        public static void DeleteCounters()
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                appStorage.DeleteFile("contracts.xml");
            }
        }

        public static void SaveCounters(List<Counter> list)
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                appStorage.DeleteFile("contracts.xml");
                using (var streamFile = appStorage.OpenFile("contracts.xml", FileMode.OpenOrCreate))
                using (var writer = new StreamWriter(streamFile))
                //write_options_state(writer, entry);
                {
                    XmlSerializer serializer = new XmlSerializer(typeof(List<Counter>));
                    serializer.Serialize(writer, list);
                }
            }
        }

        #endregion

        #region Toasts

        public static List<ToastViewModel> LoadToasts()
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (var streamFile = appStorage.OpenFile("toasts.xml", FileMode.OpenOrCreate))
                {
                    try
                    {
                        XmlSerializer serializer = new XmlSerializer(typeof(List<ToastViewModel>));
                        using (var reader = new StreamReader(streamFile))
                            return serializer.Deserialize(reader) as List<ToastViewModel>;
                    }
                    catch (Exception) { return new List<ToastViewModel>(); }
                }
            }
        }

        public static void DeleteToasts()
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                appStorage.DeleteFile("toasts.xml");
            }
        }

        public static void SaveToasts(List<ToastViewModel> list)
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                appStorage.DeleteFile("toasts.xml");
                using (var streamFile = appStorage.OpenFile("toasts.xml", FileMode.OpenOrCreate))
                using (var writer = new StreamWriter(streamFile))
                //write_options_state(writer, entry);
                {
                    XmlSerializer serializer = new XmlSerializer(typeof(List<ToastViewModel>));
                    serializer.Serialize(writer, list);
                }
            }
        }

        #endregion
        #region Ads

        public static List<Ads> LoadAds()
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (var streamFile = appStorage.OpenFile("ads.xml", FileMode.OpenOrCreate))
                {
                    try
                    {
                        XmlSerializer serializer = new XmlSerializer(typeof(List<Ads>));
                        using (var reader = new StreamReader(streamFile))
                            return serializer.Deserialize(reader) as List<Ads>;
                    }
                    catch (Exception) { return new List<Ads>(); }
                }
            }
        }

        public static void DeleteAds()
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                appStorage.DeleteFile("ads.xml");
            }
        }

        public static void SaveAds(List<Ads> list)
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                appStorage.DeleteFile("ads.xml");
                using (var streamFile = appStorage.OpenFile("ads.xml", FileMode.OpenOrCreate))
                using (var writer = new StreamWriter(streamFile))
                //write_options_state(writer, entry);
                {
                    XmlSerializer serializer = new XmlSerializer(typeof(List<Ads>));
                    serializer.Serialize(writer, list);
                }
            }
        }

        #endregion

        public static void getHTML(string query, string options, Action<string> callback, Action<string, string> callback2, Action error)
        {
            try
            {
                HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(query);
                req.Method = "GET";
                req.BeginGetResponse(
                    (asyncResult) =>
                    {
                        try
                        {
                            HttpWebResponse objResponse = null;
                            StreamReader objs = null;

                            HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState;

                            objResponse = (HttpWebResponse)request.EndGetResponse(asyncResult);
                            objs = new StreamReader(objResponse.GetResponseStream());

                            var s = objs.ReadToEnd();
                            if (callback2 != null)
                                callback2(s, options);
                            else if (callback != null)
                                callback(s);

                            return;
                        }
                        catch (Exception e)
                        {
                            e.ToString();
                            error();
                        }
                    }
                    , req);
            }
            catch (Exception)
            {
                error();
            }
        }
        public static void getHTML(string query, Action<string> callback, Action<Exception> error)
        {
            try
            {
                HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(query);
                req.Method = "GET";
                req.BeginGetResponse(
                    (asyncResult) =>
                    {
                        try
                        {
                            HttpWebResponse objResponse = null;
                            StreamReader objs = null;

                            HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState;

                            objResponse = (HttpWebResponse)request.EndGetResponse(asyncResult);
                            objs = new StreamReader(objResponse.GetResponseStream());

                            var s = objs.ReadToEnd();
                            if (callback != null)
                                callback(s);

                            return;
                        }
                        catch (Exception e)
                        {
                            e.ToString();
                            error(e);
                        }
                    }
                    , req);
            }
            catch (Exception e)
            {
                error(e);
            }
        }
        public static void getHTML(string query, Action<string> callback, Action error)
        {
            getHTML(query, "", callback, null, error);
        }


        public static void getHTML(string query, string options, Action<string, string> callback, Action error)
        {
            getHTML(query, options, null, callback, error);
        }


        #region utilizations
        public static string GetUtilizationUrl(bool isTrial)
        {
            return GetUtilizationUrl(0, isTrial);
        }
        public static string GetUtilizationUrl(int occ, bool isTrial)
        {
            var s = "http://fboscari.altervista.org/submit_Utilizzi.php?name=" +
                Config.UtilizationsName +
                (isTrial ? " Trial" : "") +
                "&id=" +
                getID();
            if (occ >= 1)
                s += "&occ=" +
                    occ;
            return s;

        }
        public static string getID()
        {
            byte[] result = null;
            object uniqueId;
            if (DeviceExtendedProperties.TryGetValue("DeviceUniqueId", out uniqueId))
                result = (byte[])uniqueId;
            var s = "";
            for (int i = 0; i < result.Length; i++)
                s += result[i];
            return s;
        }


        
        private static Func<StreamReader, int> read_utilizations = reader =>
        {

            var s = reader.ReadToEnd();
            var occ = Int16.Parse(s);


            return occ;
        };


        private static Action<StreamWriter, int> write_utilizations = (writer, occ) =>
        {
            var s = "" + occ;

            writer.Write(s);
        };



        public static void SaveUtilizations(int utilizations)
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                appStorage.DeleteFile("utilizations.txt");
                using (var streamFile = appStorage.OpenFile("utilizations.txt", FileMode.OpenOrCreate))
                using (var writer = new StreamWriter(streamFile))
                    write_utilizations(writer, utilizations);
            }
        }



        public static void DeleteUtilizations()
        {
            var appStorage = IsolatedStorageFile.GetUserStoreForApplication();
            appStorage.DeleteFile("utilizations.txt");
        }

        public static int LoadUtilizations()
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (var streamFile = appStorage.OpenFile("utilizations.txt", FileMode.OpenOrCreate))
                {
                    try
                    {
                        using (var reader = new StreamReader(streamFile))
                            return read_utilizations(reader);
                    }
                    catch (Exception)
                    {
                        appStorage.DeleteFile("utilizations.txt");
                        return 0;
                    }
                }


            }

        }
        #endregion

        #region Crack

        public static Byte[] CreateMD5Hash(string input)
        {
            var hashalg = new SHA256Managed();
            var h = hashalg.ComputeHash(Encoding.UTF8.GetBytes(input));
            return h;
        }

        public static bool CheckSavedCrack()
        {
            Byte[] saved = GetCrackFile(true);
            Byte[] hash = App.Crack_Hash;
            if (saved.Length != hash.Length)
                return false;
            for (int i = 0; i < saved.Length; i++)
                if (saved[i] != hash[i])
                    return false;
            return true;

        }

        public static bool CheckCrack(Byte[] hash)
        {
            Byte[] saved = GetCrackFile(false);
            if (saved.Length != hash.Length)
                return false;
            for (int i = 0; i < saved.Length; i++)
                if (saved[i] != hash[i])
                    return false;
            SaveCrackFile(saved);
            return true;
        }


        private static Func<StreamReader, Byte[]> read_crack_file = reader =>
        {


            var s = reader.ReadToEnd();
            var a = s.Split(new[] { ';' });
            Byte[] h = new Byte[a.Length];
            for (int i = 0; i < a.Length; i++)
                h[i] = Byte.Parse(a[i]);
            return h;

        };

        private static Action<StreamWriter, Byte[]> write_crack_file = (writer, h) =>
        {
            var s = "";
            for (int i = 0; i < h.Length - 1; i++)
                s += h[i] + ";";
            if (h.Length > 0)
                s += h[h.Length - 1];
            writer.Write(s);
        };

        public static void DeleteCrackFile()
        {
            try
            {
                using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    appStorage.DeleteFile("crack.txt");
                }
            }
            catch (Exception e)
            {
                e.ToString();
            }
        }

        public static void SaveCrackFile(Byte[] h)
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                appStorage.DeleteFile("crack.txt");
                using (var streamFile = appStorage.OpenFile("crack.txt", FileMode.OpenOrCreate))
                using (var writer = new StreamWriter(streamFile))
                    write_crack_file(writer, h);
            }
        }

        public static Byte[] GetCrackFile(bool initial_check)
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (var streamFile = appStorage.OpenFile("crack.txt", FileMode.OpenOrCreate))
                {
                    try
                    {
                        using (var reader = new StreamReader(streamFile))
                            return read_crack_file(reader);
                    }
                    catch (Exception)
                    {
                        //SaveCrackFile(StateManager.Crack_Hash);
                        if (initial_check)
                            return new Byte[0];
                        else
                            return App.Crack_Hash;
                    }
                }
            }
        }

        #endregion

        #region Disclaimer_Once
        
        public static bool IsFirstOpening()
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (var streamFile = appStorage.OpenFile("first_opening.xml", FileMode.OpenOrCreate))
                {
                    try
                    {
                        XmlSerializer serializer = new XmlSerializer(typeof(Int32));
                        using (var reader = new StreamReader(streamFile))
                            return (Int32)(serializer.Deserialize(reader))!=1;
                    }
                    catch (Exception e) {
                        e.ToString();
                        return true; 
                    }
                }
            }
        }

        public static void SetAlreadyOpened()
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (var streamFile = appStorage.OpenFile("first_opening.xml", FileMode.OpenOrCreate))
                using (var writer = new StreamWriter(streamFile))
                //write_options_state(writer, entry);
                {
                    XmlSerializer serializer = new XmlSerializer(typeof(Int32));
                    serializer.Serialize(writer, 1);
                }
            }
        }
        
        #endregion

    }
}
